﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SpiceNet.Circuits;
using SpiceNet.Diagnostics;
using SpiceNet.Parameters;

namespace SpiceNet.Models
{
    /// <summary>
    /// A model class for the BSIM1 Mosfet
    /// </summary>
    public class BSIM1Model : Model
    {
        /// <summary>
        /// Get parameters
        /// </summary>
        public override Dictionary<string, IP> ParamTable => _pTable;

        #region Parameters
        private enum _c
        {
            /* model parameters */
            BSIM1_MOD_VFB0 = 101,
            BSIM1_MOD_VFBL = 102,
            BSIM1_MOD_VFBW = 103,
            BSIM1_MOD_PHI0 = 104,
            BSIM1_MOD_PHIL = 105,
            BSIM1_MOD_PHIW = 106,
            BSIM1_MOD_K10 = 107,
            BSIM1_MOD_K1L = 108,
            BSIM1_MOD_K1W = 109,
            BSIM1_MOD_K20 = 110,
            BSIM1_MOD_K2L = 111,
            BSIM1_MOD_K2W = 112,
            BSIM1_MOD_ETA0 = 113,
            BSIM1_MOD_ETAL = 114,
            BSIM1_MOD_ETAW = 115,
            BSIM1_MOD_ETAB0 = 116,
            BSIM1_MOD_ETABL = 117,
            BSIM1_MOD_ETABW = 118,
            BSIM1_MOD_ETAD0 = 119,
            BSIM1_MOD_ETADL = 120,
            BSIM1_MOD_ETADW = 121,
            BSIM1_MOD_DELTAL = 122,
            BSIM1_MOD_DELTAW = 123,
            BSIM1_MOD_MOBZERO = 124,
            BSIM1_MOD_MOBZEROB0 = 125,
            BSIM1_MOD_MOBZEROBL = 126,
            BSIM1_MOD_MOBZEROBW = 127,
            BSIM1_MOD_MOBVDD0 = 128,
            BSIM1_MOD_MOBVDDL = 129,
            BSIM1_MOD_MOBVDDW = 130,
            BSIM1_MOD_MOBVDDB0 = 131,
            BSIM1_MOD_MOBVDDBL = 132,
            BSIM1_MOD_MOBVDDBW = 133,
            BSIM1_MOD_MOBVDDD0 = 134,
            BSIM1_MOD_MOBVDDDL = 135,
            BSIM1_MOD_MOBVDDDW = 136,
            BSIM1_MOD_UGS0 = 137,
            BSIM1_MOD_UGSL = 138,
            BSIM1_MOD_UGSW = 139,
            BSIM1_MOD_UGSB0 = 140,
            BSIM1_MOD_UGSBL = 141,
            BSIM1_MOD_UGSBW = 142,
            BSIM1_MOD_UDS0 = 143,
            BSIM1_MOD_UDSL = 144,
            BSIM1_MOD_UDSW = 145,
            BSIM1_MOD_UDSB0 = 146,
            BSIM1_MOD_UDSBL = 147,
            BSIM1_MOD_UDSBW = 148,
            BSIM1_MOD_UDSD0 = 149,
            BSIM1_MOD_UDSDL = 150,
            BSIM1_MOD_UDSDW = 151,
            BSIM1_MOD_N00 = 152,
            BSIM1_MOD_N0L = 153,
            BSIM1_MOD_N0W = 154,
            BSIM1_MOD_NB0 = 155,
            BSIM1_MOD_NBL = 156,
            BSIM1_MOD_NBW = 157,
            BSIM1_MOD_ND0 = 158,
            BSIM1_MOD_NDL = 159,
            BSIM1_MOD_NDW = 160,
            BSIM1_MOD_TOX = 161,
            BSIM1_MOD_TEMP = 162,
            BSIM1_MOD_VDD = 163,
            BSIM1_MOD_CGSO = 164,
            BSIM1_MOD_CGDO = 165,
            BSIM1_MOD_CGBO = 166,
            BSIM1_MOD_XPART = 167,
            BSIM1_MOD_RSH = 168,
            BSIM1_MOD_JS = 169,
            BSIM1_MOD_PB = 170,
            BSIM1_MOD_MJ = 171,
            BSIM1_MOD_PBSW = 172,
            BSIM1_MOD_MJSW = 173,
            BSIM1_MOD_CJ = 174,
            BSIM1_MOD_CJSW = 175,
            BSIM1_MOD_DEFWIDTH = 176,
            BSIM1_MOD_DELLENGTH = 177,
            BSIM1_MOD_NMOS = 178,
            BSIM1_MOD_PMOS = 179
        }
        private static Dictionary<string, IP> _pTable = new Dictionary<string, IP>
        {
            { "vfb", new IP(IF.IOP, (int)_c.BSIM1_MOD_VFB0, T.REAL, "Flat band voltage") },
            { "lvfb", new IP(IF.IOP, (int)_c.BSIM1_MOD_VFBL, T.REAL, "Length dependence of vfb") },
            { "wvfb", new IP(IF.IOP, (int)_c.BSIM1_MOD_VFBW, T.REAL, "Width dependence of vfb") },
            { "phi", new IP(IF.IOP, (int)_c.BSIM1_MOD_PHI0, T.REAL, "Strong inversion surface potential ") },
            { "lphi", new IP(IF.IOP, (int)_c.BSIM1_MOD_PHIL, T.REAL, "Length dependence of phi") },
            { "wphi", new IP(IF.IOP, (int)_c.BSIM1_MOD_PHIW, T.REAL, "Width dependence of phi") },
            { "k1", new IP(IF.IOP, (int)_c.BSIM1_MOD_K10, T.REAL, "Bulk effect coefficient 1") },
            { "lk1", new IP(IF.IOP, (int)_c.BSIM1_MOD_K1L, T.REAL, "Length dependence of k1") },
            { "wk1", new IP(IF.IOP, (int)_c.BSIM1_MOD_K1W, T.REAL, "Width dependence of k1") },
            { "k2", new IP(IF.IOP, (int)_c.BSIM1_MOD_K20, T.REAL, "Bulk effect coefficient 2") },
            { "lk2", new IP(IF.IOP, (int)_c.BSIM1_MOD_K2L, T.REAL, "Length dependence of k2") },
            { "wk2", new IP(IF.IOP, (int)_c.BSIM1_MOD_K2W, T.REAL, "Width dependence of k2") },
            { "eta", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETA0, T.REAL, "VDS dependence of threshold voltage") },
            { "leta", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETAL, T.REAL, "Length dependence of eta") },
            { "weta", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETAW, T.REAL, "Width dependence of eta") },
            { "x2e", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETAB0, T.REAL, "VBS dependence of eta") },
            { "lx2e", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETABL, T.REAL, "Length dependence of x2e") },
            { "wx2e", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETABW, T.REAL, "Width dependence of x2e") },
            { "x3e", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETAD0, T.REAL, "VDS dependence of eta") },
            { "lx3e", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETADL, T.REAL, "Length dependence of x3e") },
            { "wx3e", new IP(IF.IOP, (int)_c.BSIM1_MOD_ETADW, T.REAL, "Width dependence of x3e") },
            { "dl", new IP(IF.IOP, (int)_c.BSIM1_MOD_DELTAL, T.REAL, "Channel length reduction in um") },
            { "dw", new IP(IF.IOP, (int)_c.BSIM1_MOD_DELTAW, T.REAL, "Channel width reduction in um") },
            { "muz", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBZERO, T.REAL, "Zero field mobility at VDS=0 VGS=VTH") },
            { "x2mz", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBZEROB0, T.REAL, "VBS dependence of muz") },
            { "lx2mz", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBZEROBL, T.REAL, "Length dependence of x2mz") },
            { "wx2mz", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBZEROBW, T.REAL, "Width dependence of x2mz") },
            { "mus", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDD0, T.REAL, "Mobility at VDS=VDD VGS=VTH, channel length modulation") },
            { "lmus", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDL, T.REAL, "Length dependence of mus") },
            { "wmus", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDW, T.REAL, "Width dependence of mus") },
            { "x2ms", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDB0, T.REAL, "VBS dependence of mus") },
            { "lx2ms", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDBL, T.REAL, "Length dependence of x2ms") },
            { "wx2ms", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDBW, T.REAL, "Width dependence of x2ms") },
            { "x3ms", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDD0, T.REAL, "VDS dependence of mus") },
            { "lx3ms", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDDL, T.REAL, "Length dependence of x3ms") },
            { "wx3ms", new IP(IF.IOP, (int)_c.BSIM1_MOD_MOBVDDDW, T.REAL, "Width dependence of x3ms") },
            { "u0", new IP(IF.IOP, (int)_c.BSIM1_MOD_UGS0, T.REAL, "VGS dependence of mobility") },
            { "lu0", new IP(IF.IOP, (int)_c.BSIM1_MOD_UGSL, T.REAL, "Length dependence of u0") },
            { "wu0", new IP(IF.IOP, (int)_c.BSIM1_MOD_UGSW, T.REAL, "Width dependence of u0") },
            { "x2u0", new IP(IF.IOP, (int)_c.BSIM1_MOD_UGSB0, T.REAL, "VBS dependence of u0") },
            { "lx2u0", new IP(IF.IOP, (int)_c.BSIM1_MOD_UGSBL, T.REAL, "Length dependence of x2u0") },
            { "wx2u0", new IP(IF.IOP, (int)_c.BSIM1_MOD_UGSBW, T.REAL, "Width dependence of x2u0") },
            { "u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDS0, T.REAL, "VDS depence of mobility, velocity saturation") },
            { "lu1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSL, T.REAL, "Length dependence of u1") },
            { "wu1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSW, T.REAL, "Width dependence of u1") },
            { "x2u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSB0, T.REAL, "VBS depence of u1") },
            { "lx2u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSBL, T.REAL, "Length depence of x2u1") },
            { "wx2u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSBW, T.REAL, "Width depence of x2u1") },
            { "x3u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSD0, T.REAL, "VDS depence of u1") },
            { "lx3u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSDL, T.REAL, "Length dependence of x3u1") },
            { "wx3u1", new IP(IF.IOP, (int)_c.BSIM1_MOD_UDSDW, T.REAL, "Width depence of x3u1") },
            { "n0", new IP(IF.IOP, (int)_c.BSIM1_MOD_N00, T.REAL, "Subthreshold slope") },
            { "ln0", new IP(IF.IOP, (int)_c.BSIM1_MOD_N0L, T.REAL, "Length dependence of n0") },
            { "wn0", new IP(IF.IOP, (int)_c.BSIM1_MOD_N0W, T.REAL, "Width dependence of n0") },
            { "nb", new IP(IF.IOP, (int)_c.BSIM1_MOD_NB0, T.REAL, "VBS dependence of subthreshold slope") },
            { "lnb", new IP(IF.IOP, (int)_c.BSIM1_MOD_NBL, T.REAL, "Length dependence of nb") },
            { "wnb", new IP(IF.IOP, (int)_c.BSIM1_MOD_NBW, T.REAL, "Width dependence of nb") },
            { "nd", new IP(IF.IOP, (int)_c.BSIM1_MOD_ND0, T.REAL, "VDS dependence of subthreshold slope") },
            { "lnd", new IP(IF.IOP, (int)_c.BSIM1_MOD_NDL, T.REAL, "Length dependence of nd") },
            { "wnd", new IP(IF.IOP, (int)_c.BSIM1_MOD_NDW, T.REAL, "Width dependence of nd") },
            { "tox", new IP(IF.IOP, (int)_c.BSIM1_MOD_TOX, T.REAL, "Gate oxide thickness in um") },
            { "temp", new IP(IF.IOP, (int)_c.BSIM1_MOD_TEMP, T.REAL, "Temperature in degree Celcius") },
            { "vdd", new IP(IF.IOP, (int)_c.BSIM1_MOD_VDD, T.REAL, "Supply voltage to specify mus") },
            { "cgso", new IP(IF.IOPA, (int)_c.BSIM1_MOD_CGSO, T.REAL, "Gate source overlap capacitance per unit channel width(m)") },
            { "cgdo", new IP(IF.IOPA, (int)_c.BSIM1_MOD_CGDO, T.REAL, "Gate drain overlap capacitance per unit channel width(m)") },
            { "cgbo", new IP(IF.IOPA, (int)_c.BSIM1_MOD_CGBO, T.REAL, "Gate bulk overlap capacitance per unit channel length(m)") },
            { "xpart", new IP(IF.IOP, (int)_c.BSIM1_MOD_XPART, T.REAL, "Flag for channel charge partitioning") },
            { "rsh", new IP(IF.IOP, (int)_c.BSIM1_MOD_RSH, T.REAL, "Source drain diffusion sheet resistance in ohm per square") },
            { "js", new IP(IF.IOP, (int)_c.BSIM1_MOD_JS, T.REAL, "Source drain junction saturation current per unit area") },
            { "pb", new IP(IF.IOP, (int)_c.BSIM1_MOD_PB, T.REAL, "Source drain junction built in potential") },
            { "mj", new IP(IF.IOPA, (int)_c.BSIM1_MOD_MJ, T.REAL, "Source drain bottom junction capacitance grading coefficient") },
            { "pbsw", new IP(IF.IOPA, (int)_c.BSIM1_MOD_PBSW, T.REAL, "Source drain side junction capacitance built in potential") },
            { "mjsw", new IP(IF.IOPA, (int)_c.BSIM1_MOD_MJSW, T.REAL, "Source drain side junction capacitance grading coefficient") },
            { "cj", new IP(IF.IOPA, (int)_c.BSIM1_MOD_CJ, T.REAL, "Source drain bottom junction capacitance per unit area") },
            { "cjsw", new IP(IF.IOPA, (int)_c.BSIM1_MOD_CJSW, T.REAL, "Source drain side junction capacitance per unit area") },
            { "wdf", new IP(IF.IOP, (int)_c.BSIM1_MOD_DEFWIDTH, T.REAL, "Default width of source drain diffusion in um") },
            { "dell", new IP(IF.IOP, (int)_c.BSIM1_MOD_DELLENGTH, T.REAL, "Length reduction of source drain diffusion") },
            { "nmos", new IP(IF.IP, (int)_c.BSIM1_MOD_NMOS, T.FLAG, "Flag to indicate NMOS") },
            { "pmos", new IP(IF.IP, (int)_c.BSIM1_MOD_PMOS, T.FLAG, "Flag to indicate PMOS") }
        };

        public int B1type { get; private set; } = 1;
        public Parameter<double> B1vfb0 { get; } = new Parameter<double>();
        public Parameter<double> B1vfbL { get; } = new Parameter<double>();
        public Parameter<double> B1vfbW { get; } = new Parameter<double>();
        public Parameter<double> B1phi0 { get; } = new Parameter<double>();
        public Parameter<double> B1phiL { get; } = new Parameter<double>();
        public Parameter<double> B1phiW { get; } = new Parameter<double>();
        public Parameter<double> B1K10 { get; } = new Parameter<double>();
        public Parameter<double> B1K1L { get; } = new Parameter<double>();
        public Parameter<double> B1K1W { get; } = new Parameter<double>();
        public Parameter<double> B1K20 { get; } = new Parameter<double>();
        public Parameter<double> B1K2L { get; } = new Parameter<double>();
        public Parameter<double> B1K2W { get; } = new Parameter<double>();
        public Parameter<double> B1eta0 { get; } = new Parameter<double>();
        public Parameter<double> B1etaL { get; } = new Parameter<double>();
        public Parameter<double> B1etaW { get; } = new Parameter<double>();
        public Parameter<double> B1etaB0 { get; } = new Parameter<double>();
        public Parameter<double> B1etaBl { get; } = new Parameter<double>();
        public Parameter<double> B1etaBw { get; } = new Parameter<double>();
        public Parameter<double> B1etaD0 { get; } = new Parameter<double>();
        public Parameter<double> B1etaDl { get; } = new Parameter<double>();
        public Parameter<double> B1etaDw { get; } = new Parameter<double>();
        public Parameter<double> B1deltaL { get; } = new Parameter<double>();
        public Parameter<double> B1deltaW { get; } = new Parameter<double>();
        public Parameter<double> B1mobZero { get; } = new Parameter<double>();
        public Parameter<double> B1mobZeroB0 { get; } = new Parameter<double>();
        public Parameter<double> B1mobZeroBl { get; } = new Parameter<double>();
        public Parameter<double> B1mobZeroBw { get; } = new Parameter<double>();
        public Parameter<double> B1mobVdd0 { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddl { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddw { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddB0 { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddBl { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddBw { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddD0 { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddDl { get; } = new Parameter<double>();
        public Parameter<double> B1mobVddDw { get; } = new Parameter<double>();
        public Parameter<double> B1ugs0 { get; } = new Parameter<double>();
        public Parameter<double> B1ugsL { get; } = new Parameter<double>();
        public Parameter<double> B1ugsW { get; } = new Parameter<double>();
        public Parameter<double> B1ugsB0 { get; } = new Parameter<double>();
        public Parameter<double> B1ugsBL { get; } = new Parameter<double>();
        public Parameter<double> B1ugsBW { get; } = new Parameter<double>();
        public Parameter<double> B1uds0 { get; } = new Parameter<double>();
        public Parameter<double> B1udsL { get; } = new Parameter<double>();
        public Parameter<double> B1udsW { get; } = new Parameter<double>();
        public Parameter<double> B1udsB0 { get; } = new Parameter<double>();
        public Parameter<double> B1udsBL { get; } = new Parameter<double>();
        public Parameter<double> B1udsBW { get; } = new Parameter<double>();
        public Parameter<double> B1udsD0 { get; } = new Parameter<double>();
        public Parameter<double> B1udsDL { get; } = new Parameter<double>();
        public Parameter<double> B1udsDW { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlope0 { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeL { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeW { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeB0 { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeBL { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeBW { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeD0 { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeDL { get; } = new Parameter<double>();
        public Parameter<double> B1subthSlopeDW { get; } = new Parameter<double>();
        public Parameter<double> B1oxideThickness { get; } = new Parameter<double>();
        public Parameter<double> B1temp { get; } = new Parameter<double>();
        public Parameter<double> B1vdd { get; } = new Parameter<double>();
        public Parameter<double> B1gateSourceOverlapCap { get; } = new Parameter<double>();
        public Parameter<double> B1gateDrainOverlapCap { get; } = new Parameter<double>();
        public Parameter<double> B1gateBulkOverlapCap { get; } = new Parameter<double>();
        public Parameter<double> B1channelChargePartitionFlag { get; } = new Parameter<double>();
        public Parameter<double> B1sheetResistance { get; } = new Parameter<double>();
        public Parameter<double> B1jctSatCurDensity { get; } = new Parameter<double>();
        public Parameter<double> B1bulkJctPotential { get; } = new Parameter<double>();
        public Parameter<double> B1bulkJctBotGradingCoeff { get; } = new Parameter<double>();
        public Parameter<double> B1sidewallJctPotential { get; } = new Parameter<double>();
        public Parameter<double> B1bulkJctSideGradingCoeff { get; } = new Parameter<double>();
        public Parameter<double> B1unitAreaJctCap { get; } = new Parameter<double>();
        public Parameter<double> B1unitLengthSidewallJctCap { get; } = new Parameter<double>();
        public Parameter<double> B1defaultWidth { get; } = new Parameter<double>();
        public Parameter<double> B1deltaLength { get; } = new Parameter<double>();
        #endregion

        // Variables that should be transferred to the instance initialization
        public double B1Cox { get; private set; }

        /// <summary>
        /// Constructor
        /// </summary>
        public BSIM1Model(string name) : base(name) { }

        /// <summary>
        /// Set parameter
        /// </summary>
        protected override void Param(int id, object value, Circuit ckt = null)
        {
            switch ((_c)id)
            {
                case _c.BSIM1_MOD_VFB0:
                    B1vfb0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_VFBL:
                    B1vfbL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_VFBW:
                    B1vfbW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_PHI0:
                    B1phi0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_PHIL:
                    B1phiL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_PHIW:
                    B1phiW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_K10:
                    B1K10.Par((double)value);
                    break;
                case _c.BSIM1_MOD_K1L:
                    B1K1L.Par((double)value);
                    break;
                case _c.BSIM1_MOD_K1W:
                    B1K1W.Par((double)value);
                    break;
                case _c.BSIM1_MOD_K20:
                    B1K20.Par((double)value);
                    break;
                case _c.BSIM1_MOD_K2L:
                    B1K2L.Par((double)value);
                    break;
                case _c.BSIM1_MOD_K2W:
                    B1K2W.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETA0:
                    B1eta0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETAL:
                    B1etaL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETAW:
                    B1etaW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETAB0:
                    B1etaB0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETABL:
                    B1etaBl.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETABW:
                    B1etaBw.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETAD0:
                    B1etaD0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETADL:
                    B1etaDl.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ETADW:
                    B1etaDw.Par((double)value);
                    break;
                case _c.BSIM1_MOD_DELTAL:
                    B1deltaL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_DELTAW:
                    B1deltaW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBZERO:
                    B1mobZero.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBZEROB0:
                    B1mobZeroB0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBZEROBL:
                    B1mobZeroBl.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBZEROBW:
                    B1mobZeroBw.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDD0:
                    B1mobVdd0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDL:
                    B1mobVddl.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDW:
                    B1mobVddw.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDB0:
                    B1mobVddB0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDBL:
                    B1mobVddBl.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDBW:
                    B1mobVddBw.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDD0:
                    B1mobVddD0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDDL:
                    B1mobVddDl.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MOBVDDDW:
                    B1mobVddDw.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UGS0:
                    B1ugs0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UGSL:
                    B1ugsL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UGSW:
                    B1ugsW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UGSB0:
                    B1ugsB0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UGSBL:
                    B1ugsBL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UGSBW:
                    B1ugsBW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDS0:
                    B1uds0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSL:
                    B1udsL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSW:
                    B1udsW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSB0:
                    B1udsB0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSBL:
                    B1udsBL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSBW:
                    B1udsBW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSD0:
                    B1udsD0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSDL:
                    B1udsDL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_UDSDW:
                    B1udsDW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_N00:
                    B1subthSlope0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_N0L:
                    B1subthSlopeL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_N0W:
                    B1subthSlopeW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_NB0:
                    B1subthSlopeB0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_NBL:
                    B1subthSlopeBL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_NBW:
                    B1subthSlopeBW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_ND0:
                    B1subthSlopeD0.Par((double)value);
                    break;
                case _c.BSIM1_MOD_NDL:
                    B1subthSlopeDL.Par((double)value);
                    break;
                case _c.BSIM1_MOD_NDW:
                    B1subthSlopeDW.Par((double)value);
                    break;
                case _c.BSIM1_MOD_TOX:
                    B1oxideThickness.Par((double)value);
                    break;
                case _c.BSIM1_MOD_TEMP:
                    B1temp.Par((double)value);
                    break;
                case _c.BSIM1_MOD_VDD:
                    B1vdd.Par((double)value);
                    break;
                case _c.BSIM1_MOD_CGSO:
                    B1gateSourceOverlapCap.Par((double)value);
                    break;
                case _c.BSIM1_MOD_CGDO:
                    B1gateDrainOverlapCap.Par((double)value);
                    break;
                case _c.BSIM1_MOD_CGBO:
                    B1gateBulkOverlapCap.Par((double)value);
                    break;
                case _c.BSIM1_MOD_XPART:
                    B1channelChargePartitionFlag.Par((int)value);
                    break;
                case _c.BSIM1_MOD_RSH:
                    B1sheetResistance.Par((double)value);
                    break;
                case _c.BSIM1_MOD_JS:
                    B1jctSatCurDensity.Par((double)value);
                    break;
                case _c.BSIM1_MOD_PB:
                    B1bulkJctPotential.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MJ:
                    B1bulkJctBotGradingCoeff.Par((double)value);
                    break;
                case _c.BSIM1_MOD_PBSW:
                    B1sidewallJctPotential.Par((double)value);
                    break;
                case _c.BSIM1_MOD_MJSW:
                    B1bulkJctSideGradingCoeff.Par((double)value);
                    break;
                case _c.BSIM1_MOD_CJ:
                    B1unitAreaJctCap.Par((double)value);
                    break;
                case _c.BSIM1_MOD_CJSW:
                    B1unitLengthSidewallJctCap.Par((double)value);
                    break;
                case _c.BSIM1_MOD_DEFWIDTH:
                    B1defaultWidth.Par((double)value);
                    break;
                case _c.BSIM1_MOD_DELLENGTH:
                    B1deltaLength.Par((double)value);
                    break;
                case _c.BSIM1_MOD_NMOS:
                    B1type = 1;
                    break;
                case _c.BSIM1_MOD_PMOS:
                    B1type = -1;
                    break;
                default:
                    throw new BadParameterException();
            }
        }

        /// <summary>
        /// Ask parameter
        /// </summary>
        protected override object Ask(int id, Circuit ckt = null)
        {
            switch ((_c)id)
            {
                case _c.BSIM1_MOD_VFB0:
                    return B1vfb0.Value;
                case _c.BSIM1_MOD_VFBL:
                    return B1vfbL.Value;
                case _c.BSIM1_MOD_VFBW:
                    return B1vfbW.Value;
                case _c.BSIM1_MOD_PHI0:
                    return B1phi0.Value;
                case _c.BSIM1_MOD_PHIL:
                    return B1phiL.Value;
                case _c.BSIM1_MOD_PHIW:
                    return B1phiW.Value;
                case _c.BSIM1_MOD_K10:
                    return B1K10.Value;
                case _c.BSIM1_MOD_K1L:
                    return B1K1L.Value;
                case _c.BSIM1_MOD_K1W:
                    return B1K1W.Value;
                case _c.BSIM1_MOD_K20:
                    return B1K20.Value;
                case _c.BSIM1_MOD_K2L:
                    return B1K2L.Value;
                case _c.BSIM1_MOD_K2W:
                    return B1K2W.Value;
                case _c.BSIM1_MOD_ETA0:
                    return B1eta0.Value;
                case _c.BSIM1_MOD_ETAL:
                    return B1etaL.Value;
                case _c.BSIM1_MOD_ETAW:
                    return B1etaW.Value;
                case _c.BSIM1_MOD_ETAB0:
                    return B1etaB0.Value;
                case _c.BSIM1_MOD_ETABL:
                    return B1etaBl.Value;
                case _c.BSIM1_MOD_ETABW:
                    return B1etaBw.Value;
                case _c.BSIM1_MOD_ETAD0:
                    return B1etaD0.Value;
                case _c.BSIM1_MOD_ETADL:
                    return B1etaDl.Value;
                case _c.BSIM1_MOD_ETADW:
                    return B1etaDw.Value;
                case _c.BSIM1_MOD_DELTAL:
                    return B1deltaL.Value;
                case _c.BSIM1_MOD_DELTAW:
                    return B1deltaW.Value;
                case _c.BSIM1_MOD_MOBZERO:
                    return B1mobZero.Value;
                case _c.BSIM1_MOD_MOBZEROB0:
                    return B1mobZeroB0.Value;
                case _c.BSIM1_MOD_MOBZEROBL:
                    return B1mobZeroBl.Value;
                case _c.BSIM1_MOD_MOBZEROBW:
                    return B1mobZeroBw.Value;
                case _c.BSIM1_MOD_MOBVDD0:
                    return B1mobVdd0.Value;
                case _c.BSIM1_MOD_MOBVDDL:
                    return B1mobVddl.Value;
                case _c.BSIM1_MOD_MOBVDDW:
                    return B1mobVddw.Value;
                case _c.BSIM1_MOD_MOBVDDB0:
                    return B1mobVddB0.Value;
                case _c.BSIM1_MOD_MOBVDDBL:
                    return B1mobVddBl.Value;
                case _c.BSIM1_MOD_MOBVDDBW:
                    return B1mobVddBw.Value;
                case _c.BSIM1_MOD_MOBVDDD0:
                    return B1mobVddD0.Value;
                case _c.BSIM1_MOD_MOBVDDDL:
                    return B1mobVddDl.Value;
                case _c.BSIM1_MOD_MOBVDDDW:
                    return B1mobVddDw.Value;
                case _c.BSIM1_MOD_UGS0:
                    return B1ugs0.Value;
                case _c.BSIM1_MOD_UGSL:
                    return B1ugsL.Value;
                case _c.BSIM1_MOD_UGSW:
                    return B1ugsW.Value;
                case _c.BSIM1_MOD_UGSB0:
                    return B1ugsB0.Value;
                case _c.BSIM1_MOD_UGSBL:
                    return B1ugsBL.Value;
                case _c.BSIM1_MOD_UGSBW:
                    return B1ugsBW.Value;
                case _c.BSIM1_MOD_UDS0:
                    return B1uds0.Value;
                case _c.BSIM1_MOD_UDSL:
                    return B1udsL.Value;
                case _c.BSIM1_MOD_UDSW:
                    return B1udsW.Value;
                case _c.BSIM1_MOD_UDSB0:
                    return B1udsB0.Value;
                case _c.BSIM1_MOD_UDSBL:
                    return B1udsBL.Value;
                case _c.BSIM1_MOD_UDSBW:
                    return B1udsBW.Value;
                case _c.BSIM1_MOD_UDSD0:
                    return B1udsD0.Value;
                case _c.BSIM1_MOD_UDSDL:
                    return B1udsDL.Value;
                case _c.BSIM1_MOD_UDSDW:
                    return B1udsDW.Value;
                case _c.BSIM1_MOD_N00:
                    return B1subthSlope0.Value;
                case _c.BSIM1_MOD_N0L:
                    return B1subthSlopeL.Value;
                case _c.BSIM1_MOD_N0W:
                    return B1subthSlopeW.Value;
                case _c.BSIM1_MOD_NB0:
                    return B1subthSlopeB0.Value;
                case _c.BSIM1_MOD_NBL:
                    return B1subthSlopeBL.Value;
                case _c.BSIM1_MOD_NBW:
                    return B1subthSlopeBW.Value;
                case _c.BSIM1_MOD_ND0:
                    return B1subthSlopeD0.Value;
                case _c.BSIM1_MOD_NDL:
                    return B1subthSlopeDL.Value;
                case _c.BSIM1_MOD_NDW:
                    return B1subthSlopeDW.Value;
                case _c.BSIM1_MOD_TOX:
                    return B1oxideThickness.Value;
                case _c.BSIM1_MOD_TEMP:
                    return B1temp.Value;
                case _c.BSIM1_MOD_VDD:
                    return B1vdd.Value;
                case _c.BSIM1_MOD_CGSO:
                    return B1gateSourceOverlapCap.Value;
                case _c.BSIM1_MOD_CGDO:
                    return B1gateDrainOverlapCap.Value;
                case _c.BSIM1_MOD_CGBO:
                    return B1gateBulkOverlapCap.Value;
                case _c.BSIM1_MOD_XPART:
                    return B1channelChargePartitionFlag.Value;
                case _c.BSIM1_MOD_RSH:
                    return B1sheetResistance.Value;
                case _c.BSIM1_MOD_JS:
                    return B1jctSatCurDensity.Value;
                case _c.BSIM1_MOD_PB:
                    return B1bulkJctPotential.Value;
                case _c.BSIM1_MOD_MJ:
                    return B1bulkJctBotGradingCoeff.Value;
                case _c.BSIM1_MOD_PBSW:
                    return B1sidewallJctPotential.Value;
                case _c.BSIM1_MOD_MJSW:
                    return B1bulkJctSideGradingCoeff.Value;
                case _c.BSIM1_MOD_CJ:
                    return B1unitAreaJctCap.Value;
                case _c.BSIM1_MOD_CJSW:
                    return B1unitLengthSidewallJctCap.Value;
                case _c.BSIM1_MOD_DEFWIDTH:
                    return B1defaultWidth.Value;
                case _c.BSIM1_MOD_DELLENGTH:
                    return B1deltaLength.Value;
                default:
                    throw new BadParameterException();
            }
        }

        /// <summary>
        /// Temperature dependent initialization
        /// </summary>
        /// <param name="ckt"></param>
        public override void Temperature(Circuit ckt)
        {
            double Cox;

            /* Default value Processing for B1 MOSFET Models */
            /* Some Limiting for Model Parameters */
            if (B1bulkJctPotential < 0.1)
                B1bulkJctPotential.Value = 0.1;
            if (B1sidewallJctPotential < 0.1)
                B1sidewallJctPotential.Value = 0.1;

            Cox = 3.453e-13 / (B1oxideThickness * 1.0e-4);/*in F/cm**2 */
            B1Cox = Cox;     /* unit:  F/cm**2  */

            base.Temperature(ckt);
        }
    }
}
